﻿#include "stdafx.h"
#include "EditListBox.h"
#include "../Misc/StringUlities.h"
#include "../Logic/TokenConfirmer.h"

#define		CHECK_EDIT_STATUS_TIMER_ID		111   // 检查编辑状态时钟ID


CEditListBox::CEditListBox()
	:CHmjListBox()
{
	m_selectedBackBrush.CreateSolidBrush(m_selectedBackColor);
	m_nEditIndex = -1;
}


CEditListBox::~CEditListBox()
{
	m_selectedBackBrush.DeleteObject();
	m_szIds.RemoveAll();
}

// 在尾部添加细目
// szItemName:输入参数，细目名称
// dblVal:输入参数，细目数值
int CEditListBox::AddString(const CString& szItemName, double dblVal)
{
	int nItem = m_szIds.Add(szItemName);
	m_dblVals.Add(dblVal);
	InsertString(-1, m_szIds.GetAt(nItem));

	return nItem;
}

// 设置细目的数值
// nIndex:输入参数，细目索引
// dblVal:输入参数，细目数值
void CEditListBox::SetVal(int nIndex, double dblVal)
{
	int nCount = m_dblVals.GetCount();
	if (0 <= nIndex && nIndex < nCount)
	{
		m_dblVals[nIndex] = dblVal;
		if (GetSafeHwnd())
		{
			CRect rcItem;
			GetItemRect(nIndex, &rcItem);
			InvalidateRect(&rcItem);
		}
	}
}

// 查询细目的名称和数值
// nIndex:输入参数，细目索引
// szItemName:输出参数，接收细目名称
// dblVal:输出参数，接收细目数值
// 返回值:
//   TRUE - 成功， FALSE - 有错误
BOOL CEditListBox::GetVal(int nIndex, CString& szItemName, double& dblVal)
{
	int nCount = m_dblVals.GetCount();
	if (0 <= nIndex && nIndex < nCount)
	{
		szItemName = m_szIds[nIndex];
		dblVal = m_dblVals[nIndex];
		return TRUE;
	}

	return FALSE;
}


BEGIN_MESSAGE_MAP(CEditListBox, CHmjListBox)
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CTLCOLOR()
	ON_WM_VSCROLL()
	ON_WM_TIMER()
END_MESSAGE_MAP()


void CEditListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	m_nEditIndex = GetCurSel();
	
	if (m_nEditIndex >= 0)
	{
		m_edit.SetFont(&m_font);
		CString szVal = GetDoubleText(m_dblVals[m_nEditIndex]);
		m_edit.SetWindowText(szVal);

		ShowEditCtrl();
	}
}

void CEditListBox::ShowEditCtrl()
{
	if (m_nEditIndex < 0)
		return;
	if(m_edit.IsWindowVisible())
		return;

	CRect rcItem;
	GetItemRect(m_nEditIndex, &rcItem);

	CString szText = m_szIds[m_nEditIndex];
	szText += L":";

	CClientDC dc(this);
	CFont* pFont = dc.SelectObject(&m_font);
	CRect rcText(0, 0, 1, 1);
	dc.DrawText(szText, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_CALCRECT);
	dc.SelectObject(pFont);

	rcItem.left += rcText.Width();
	if (rcItem.Width() < 40)
	{
		rcItem.left = rcItem.right - 40;
	}
	rcItem.top += (rcItem.Height() - rcText.Height()) / 2;
	rcItem.bottom = rcItem.top + rcText.Height();
	rcItem.InflateRect(0, 4);
	m_edit.MoveWindow(&rcItem);
	m_edit.ShowWindow(SW_SHOW);

	m_edit.SetSel(0, -1);

	m_edit.SetFocus();

	SetTimer(CHECK_EDIT_STATUS_TIMER_ID, 50, NULL);
}


void CEditListBox::PreSubclassWindow()
{
	m_edit.Create(WS_CHILD | ES_CENTER | ES_AUTOHSCROLL,
		CRect(0, 0, 2, 2), this, 100);

	CHmjListBox::PreSubclassWindow();
}


HBRUSH CEditListBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	pDC->SetTextColor(m_selectedTextColor);
	pDC->SetBkColor(m_selectedBackColor);

	return (HBRUSH)m_selectedBackBrush;
}


void CEditListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	if (lpDrawItemStruct->CtlType != ODT_LISTBOX)
		return;

	CRect rcItem(lpDrawItemStruct->rcItem);

	LPCWSTR lpText = (LPCWSTR)lpDrawItemStruct->itemData;
	if (lpText == NULL)
		return;

	CString szText(lpText);

	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);

	COLORREF crOldTextColor = dc.GetTextColor();
	COLORREF crOldBkColor = dc.GetBkColor();
	CFont* pFont = dc.SelectObject(&m_font);

	szText += L":";

	if (m_nEditIndex >= 0 && lpDrawItemStruct->itemID == m_nEditIndex)
	{		
		dc.SetTextColor(m_selectedTextColor);
		dc.SetBkColor(m_selectedBackColor);
		dc.FillSolidRect(&rcItem, m_selectedBackColor);
	}
	else
	{
		CString szVal = GetDoubleText(m_dblVals[lpDrawItemStruct->itemID]);
		szText += szVal;

		dc.SetTextColor(m_textColor);
		dc.SetBkColor(m_backColor);
		dc.FillSolidRect(&rcItem, m_backColor);
	}

	dc.DrawText(szText, &rcItem, DT_LEFT | DT_SINGLELINE | DT_VCENTER);

	dc.SetTextColor(crOldTextColor);
	dc.SetBkColor(crOldBkColor);
	dc.SelectObject(pFont);

	dc.Detach();
}


BOOL CEditListBox::DestroyWindow()
{
	m_edit.DestroyWindow();

	return CHmjListBox::DestroyWindow();
}


void CEditListBox::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	CancelEdit();

	CHmjListBox::OnVScroll(nSBCode, nPos, pScrollBar);
}


BOOL CEditListBox::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message == WM_KEYDOWN)
	{
		if (pMsg->wParam == VK_RETURN)
		{
			if (m_edit.GetSafeHwnd() == pMsg->hwnd)
			{
				SaveEditVal();
				return TRUE;
			}
		}
	}

	return CHmjListBox::PreTranslateMessage(pMsg);
}


void CEditListBox::SaveEditVal()
{
	if (m_nEditIndex < 0)
		return;

	CTokenConfirmer  tokenConfirmer;

	CString szVal;
	m_edit.GetWindowText(szVal);
	szVal.Trim();
	if (!tokenConfirmer.IsDecimalVal(szVal))
	{
		CString szMsg;
		szMsg.Format(L"“%s”不是十进制数值！", szVal);
		MessageBox(szMsg, L"输入数值", MB_OK | MB_ICONEXCLAMATION);
		return;
	}

	double dblVal = _wtof(szVal);
	SetVal(m_nEditIndex, dblVal);

	CancelEdit();
}

void CEditListBox::CancelEdit()
{
	KillTimer(CHECK_EDIT_STATUS_TIMER_ID);

	int nOldEditIndex = m_nEditIndex;
	m_nEditIndex = -1;
	m_edit.ShowWindow(SW_HIDE);
	if (nOldEditIndex >= 0)
	{
		if (GetSafeHwnd())
		{
			CRect rcItem;
			GetItemRect(nOldEditIndex, &rcItem);
			InvalidateRect(&rcItem);
		}
	}
}


void CEditListBox::OnTimer(UINT_PTR nIDEvent)
{
	if (CHECK_EDIT_STATUS_TIMER_ID == nIDEvent)
	{
		if (m_nEditIndex >= 0)
		{
			if (GetActiveWindow()->GetSafeHwnd() != GetParent()->GetSafeHwnd())
			{
				CancelEdit();
			}
			else
			{
				CWnd* pFocus = GetFocus();
				if (pFocus)
				{
					if (pFocus->GetSafeHwnd() != m_edit.GetSafeHwnd())
						CancelEdit();
				}
			}
		}
	}

	CHmjListBox::OnTimer(nIDEvent);
}

void CEditListBox::CheckEditStatus(MSG* const pMsg)
{
	if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_MBUTTONDOWN || pMsg->message == WM_RBUTTONDOWN)
	{
		if (pMsg->hwnd != m_edit.GetSafeHwnd())
			CancelEdit();
	}
}